home *** CD-ROM | disk | FTP | other *** search
- /******-----------------------------------------------------******
- * rawdevices - a multi-devices driver for raw floppy disks *
- * for PURE_C 1.1 *
- * *
- * This is Dave Gymer's raw MiNT floppy device hacked up *
- * by Stephane Boisson (boisso_s@epita.fr) *
- * and is hereby placed in the public domain. *
- * *
- ******-----------------------------------------------------******/
-
- #include <tos.h> /* for Floprd & Flopwr */
- #include <string.h>
- #include <mint\filesys.h>
- #include <mint\kernel.h>
- #include <mint\atarierr.h>
-
- #pragma warn -par
- #pragma warn -pro
-
- #define DEBUG__(x) DEBUG(x)
- #define TRACE__(x) /* TRACE(x) */
- #define ALERT__(x) ALERT(x)
- #define FATAL__(x) FATAL(x)
-
- static long cdecl floppy_open(FILEPTR *f);
- static long cdecl floppy_write(FILEPTR *f, char *buf, long bytes);
- static long cdecl floppy_read(FILEPTR *f, char *buf, long bytes);
- static long cdecl floppy_lseek(FILEPTR *f, long where, int whence);
- static long cdecl floppy_ioctl(FILEPTR *f, int mode, void *buf);
- static long cdecl floppy_datime(FILEPTR *f, short *timeptr, int wrflag);
- static long cdecl floppy_close(FILEPTR *f, int pid);
- static long cdecl floppy_select(FILEPTR *f, long proc, int mode);
- static void cdecl floppy_unselect(FILEPTR *f, long proc, int mode);
-
- static DEVDRV floppy_device = {
- floppy_open, floppy_write, floppy_read, floppy_lseek, floppy_ioctl,
- floppy_datime, floppy_close, floppy_select, floppy_unselect,
- 0, 0, 0
- };
-
- typedef struct {
- char *name; /* Device name */
- int drive; /* BIOS drive number, 0 == A:, 1 == B: */
- int tracks; /* tracks per disk */
- int sides; /* sides per track */
- int sectors; /* sectors per track */
- int secsize; /* bytes per sector */
- long blocksize; /* calculated... */
- } RAWDEV;
-
- /* characteristics of the floppies*/
- static RAWDEV drivers[]= {
- {"fd0", 0, 80, 2, 9, 512}, /* 720 kbyte Double density */
- {"fh0", 0, 80, 2, 18, 512}, /* 1.44 meg high density */
- {"fx0", 0, 80, 2, 20, 512} /* 1.6 meg fat high density */
- };
-
-
- /* kernel information */
- struct kerinfo *kernel;
-
- /* Install time, for floppy_datime. */
- static int install_date;
- static int install_time;
-
- /* structure to hold a block buffer */
- typedef struct floppy_block {
- short dev_id;
- int track;
- int side;
- long byte;
- enum {
- INVALID, VALID, DIRTY, ATEOF
- } state;
- char *buffer;
- } FLOBLOCK;
-
- static char name[32]="u:\\dev\\";
-
- struct dev_descr devinfo = {
- &floppy_device, 0, 0, (struct tty *)0, 0L, 0L, 0L, 0L
- };
-
-
- /**
- * Initial setup, return the device driver to the OS
- **/
- DEVDRV * cdecl floppy_init(struct kerinfo *k)
- {
- long result;
- int i, len;
-
- kernel= k;
- TRACE__(("[RAWDEV] floppy_init: init raw devices"));
- len= strlen(name);
- CCONWS("Raw floppy devices for MiNT (" __DATE__ ")\r\n");
- for(i=0; i<(sizeof(drivers) / sizeof(RAWDEV)); i++)
- {
- strcpy(name+len, drivers[i].name);
- devinfo.dinfo= i;
- drivers[i].blocksize= ((long) drivers[i].secsize) * drivers[i].sectors;
- TRACE__(("[RAWDEV] floppy_init: device [%s]", name));
- if(DCNTL(DEV_INSTALL, name, (long)&devinfo)<=0)
- ALERT__(("[RAWDEV] floppy_init: Unable to install %s", name));
- }
- install_time= TGETTIME();
- install_date= TGETDATE();
-
- return((DEVDRV *) 1L);
- }
-
- /*****
- * utility functions
- * note that blocks are whole tracks
- *****/
-
- /*>>>>>>>>>>>>>>>>>>>>>> read a block <<<<<<<<<<<<<<<<<<<<<<<<*/
- static int read_block(FLOBLOCK *floblock)
- {
- int rv;
-
- TRACE__(("[RAWDEV] read_block: drive #%d, track #%d, side %d",
- drivers[floblock->dev_id].drive, floblock->track, floblock->side));
-
- rv = Floprd(floblock->buffer, 0L, drivers[floblock->dev_id].drive,
- 1, floblock->track, floblock->side,
- drivers[floblock->dev_id].sectors);
-
- if (rv)
- {
- DEBUG__(("[RAWDEV] read_block: Floprd error #%d", rv));
- floblock->state = INVALID;
- }
- else
- floblock->state = VALID;
- return(rv);
- }
-
- /*>>>>>>>>>>>>>>>>>>>> flush a block <<<<<<<<<<<<<<<<<<<<<<<<<<*/
- static int flush_block(FLOBLOCK *floblock)
- {
- int rv;
-
- if (floblock->state != DIRTY)
- return 0;
-
- TRACE__(("[RAWDEV] flush_block: drive #%d, track #%d, side %d",
- drivers[floblock->dev_id].drive, floblock->track, floblock->side));
-
- rv = Flopwr(floblock->buffer, 0L, drivers[floblock->dev_id].drive,
- 1, floblock->track, floblock->side,
- drivers[floblock->dev_id].sectors);
-
- if (rv)
- DEBUG__(("[RAWDEV] flush_block: Flopwr error #%d", rv));
- else
- floblock->state = VALID;
- return(rv);
- }
-
- /*>>>>>>>> convert long seek position into floppy_block <<<<<<<<*/
- static void seek2int(long pos, FLOBLOCK *floblock)
- {
- TRACE__(("[RAWDEV] seek2int: convert long seek position #%ld", pos));
- if (pos < 0) pos = 0;
- floblock->byte = pos % drivers[floblock->dev_id].blocksize;
- pos /= drivers[floblock->dev_id].blocksize;
- floblock->side = (int)(pos % drivers[floblock->dev_id].sides);
- pos /= drivers[floblock->dev_id].sides;
- floblock->track = (int)pos;
-
- if (floblock->track >= drivers[floblock->dev_id].tracks)
- {
- floblock->track = drivers[floblock->dev_id].tracks;
- floblock->side = 0;
- floblock->byte = 0;
- floblock->state = ATEOF;
- }
- }
-
- /*>>>>>>>> convert floppy_block into long seek position <<<<<<<*/
- static long int2seek(FLOBLOCK *floblock)
- {
- TRACE__(("[RAWDEV] int2seek: convert floppy_block"));
- return ((long)floblock->track * drivers[floblock->dev_id].sides
- + floblock->side) * drivers[floblock->dev_id].blocksize + floblock->byte;
- }
-
- /*>>>> move to next block - read it, after flushing the old one <<<<<*/
- static int next_block(FLOBLOCK *floblock)
- {
- int rv = 0;
-
- TRACE__(("[RAWDEV] next_block: move to next block"));
- if (floblock->state != ATEOF)
- {
- rv = flush_block(floblock);
- if (++floblock->side == drivers[floblock->dev_id].sides)
- {
- floblock->side = 0;
- if (++floblock->track == drivers[floblock->dev_id].tracks)
- {
- DEBUG__(("[RAWDEV] next_block: end of file"));
- floblock->state = ATEOF;
- floblock->side = 0;
- }
- }
- if (floblock->state != ATEOF)
- if (rv)
- floblock->state = INVALID;
- else
- rv = read_block(floblock);
- floblock->byte = 0;
- }
- return(rv);
- }
-
- /*****
- * here are the actual device driver functions
- *****/
- static long cdecl floppy_open(FILEPTR *f)
- {
- FLOBLOCK *floblock;
-
- TRACE__(("[RAWDEV] floppy_open: open device %s", drivers[f->fc.aux].name));
- floblock = (FLOBLOCK *)kmalloc(sizeof(FLOBLOCK));
- if (!floblock)
- {
- ALERT__(("[RAWDEV] floppy_open: out of memory for FLOBLOCK"));
- return (ENSMEM);
- }
-
- floblock->buffer = (char *)kmalloc(drivers[f->fc.aux].blocksize);
- if (!floblock->buffer)
- {
- ALERT__(("[RAWDEV] floppy_open: out of memory for blocksize"));
- return (ENSMEM);
- }
-
- f->devinfo = (long)floblock;
- floblock->state = INVALID;
- floblock->track = 0;
- floblock->side = 0;
- floblock->byte = 0;
- floblock->dev_id= f->fc.aux;
- return (0);
- }
-
- static long cdecl floppy_write(FILEPTR *f, char *buf, long bytes)
- {
- FLOBLOCK *floblock = (FLOBLOCK *)f->devinfo;
- int rv = 0;
- long bytes_written = 0;
-
- TRACE__(("[RAWDEV] floppy_write: write %ld bytes to %s", bytes, drivers[f->fc.aux].name));
-
- if (floblock->state == INVALID) rv= read_block(floblock); /* not started yet */
-
- /* keep going until we've written enough, or there's an error or EOF */
- while (!rv && floblock->state != ATEOF && bytes)
- {
- if (floblock->byte < drivers[floblock->dev_id].blocksize) /* data in buffer */
- {
- char *ptr = floblock->buffer + floblock->byte;
- long num = drivers[floblock->dev_id].blocksize - floblock->byte;
-
- if (num > bytes) num = bytes;
- bytes_written += num;
- bytes -= num;
- floblock->byte += num;
- while (num--) *ptr++ = *buf++;
- /* memcpy(ptr, buf, num); */
- floblock->state = DIRTY;
- }
- else /* must get next block */
- rv = next_block(floblock);
- }
- return rv ? rv : bytes_written;
- }
-
- static long cdecl floppy_read(FILEPTR *f, char *buf, long bytes)
- {
- FLOBLOCK *floblock = (FLOBLOCK *)f->devinfo;
- int rv = 0;
- long bytes_read = 0;
-
- TRACE__(("[RAWDEV] floppy_read: read %ld bytes from %s", bytes, drivers[f->fc.aux].name));
- if (floblock->state == INVALID) rv = read_block(floblock); /* not started yet */
-
- /* keep going until we've read enough, or there's an error or EOF */
- while (!rv && floblock->state != ATEOF && bytes)
- {
- if (floblock->byte < drivers[floblock->dev_id].blocksize) /* data in buffer */
- {
- char *ptr = floblock->buffer + floblock->byte;
- long num = drivers[floblock->dev_id].blocksize - floblock->byte;
-
- if (num > bytes) num = bytes;
- bytes_read += num;
- bytes -= num;
- floblock->byte += num;
- while (num--) *buf++ = *ptr++;
- /* memcpy(buf, ptr, num); */
- }
- else /* must get next block */
- rv = next_block(floblock);
- }
- return rv ? rv : bytes_read;
- }
-
- static long cdecl floppy_lseek(FILEPTR *f, long where, int whence)
- {
- long newpos = where;
- FLOBLOCK *floblock = (FLOBLOCK *)f->devinfo;
-
- TRACE__(("[RAWDEV] floppy_lseek: seek mode %d of %ld on %s", whence, where, drivers[f->fc.aux].name));
- switch (whence)
- {
- case SEEK_SET:
- break;
- case SEEK_CUR:
- newpos += int2seek(floblock);
- break;
- case SEEK_END:
- newpos = drivers[floblock->dev_id].sides
- * drivers[floblock->dev_id].tracks * drivers[floblock->dev_id].blocksize - newpos;
- break;
- default:
- DEBUG__(("[RAWDEV] floppy_lseek: illegal whence (%d) in seek for %s", whence, drivers[floblock->dev_id].name));
- return ERANGE;
- }
- if (int2seek(floblock) % drivers[floblock->dev_id].blocksize != newpos % drivers[floblock->dev_id].blocksize)
- {
- if (flush_block(floblock))
- DEBUG__(("[RAWDEV] floppy_lseek: flush_block failed on %s",drivers[floblock->dev_id].name));
- floblock->state = INVALID;
- }
- seek2int(newpos, floblock);
- return newpos;
- }
-
- static long cdecl floppy_ioctl(FILEPTR *f, int mode, void *buf)
- {
- TRACE__(("[RAWDEV] floppy_ioctl: mode %d on %s", mode, drivers[f->fc.aux].name));
- switch (mode) {
- case FIONREAD:
- case FIONWRITE:
- /*
- * we never block - use BLOCKSIZE as a sensible
- * number to read as a chunk
- */
- *((long *)buf) = drivers[f->fc.aux].secsize * drivers[f->fc.aux].sectors ;
- TRACE__(("[RAWDEV] floppy_ioctl: FIONREAD/FIONWRITE on %s -> %ld", drivers[f->fc.aux].name, *((long *)buf)));
- return (0);
- default:
- return EINTRN;
- }
- }
-
- static long cdecl floppy_datime(FILEPTR *f, short *timeptr, int wrflag)
- {
- TRACE__(("[RAWDEV] floppy_datime: on %s", drivers[f->fc.aux].name));
- if (wrflag) return EINVFN;
- *timeptr++ = install_time;
- *timeptr = install_date;
- return (0);
- }
-
- static long cdecl floppy_close(FILEPTR *f, int pid)
- {
- int rv = 0;
- FLOBLOCK *floblock = (FLOBLOCK *)f->devinfo;
-
- TRACE__(("[RAWDEV] floppy_close: %s by pid #%d", drivers[f->fc.aux].name, pid));
- if (!f->links) {
- rv = flush_block(floblock); /* flush the buffer */
- kfree(floblock->buffer);
- kfree(floblock);
- }
- return rv;
- }
-
- static long cdecl floppy_select(FILEPTR *f, long proc, int mode)
- {
- TRACE__(("[RAWDEV] floppy_select: %s always ready!", drivers[f->fc.aux].name));
- return 1; /* we're always ready for I/O */
- }
-
- static void cdecl floppy_unselect(FILEPTR *f, long proc, int mode)
- {
- TRACE__(("[RAWDEV] floppy_unselect: %s (nothing to do)", drivers[f->fc.aux].name));
- /* nothing for us to do here */
- }
-